package com.jinmdz.fmis.core.wrapper;

import com.jinmdz.fmis.core.annotation.AnAuthorize;
import com.jinmdz.fmis.core.annotation.AnAuthorizes;
import com.jinmdz.fmis.core.constant.Constants;
import com.jinmdz.fmis.core.model.HandlerInfo;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * Handler 封装处理类
 *
 * @author LiCongLu
 * @date 2019-12-27 16:11
 */
public final class HandlerWrapper {
    /**
     * 获取所有注册的处理器
     *
     * @param restMap RestController注解的集合
     * @return
     * @author LiCongLu
     * @date 2019-12-27 16:27
     */
    public static HashMap<String, HandlerInfo> getHandlers(Map<String, Object> restMap) {
        // 创建处理结果
        HashMap<String, HandlerInfo> handlers = new HashMap<>(16);

        // 判断是否有集合
        if (restMap == null || restMap.isEmpty()) {
            return handlers;
        }

        // 遍历循环解析
        for (Map.Entry<String, Object> entry : restMap.entrySet()) {
            // 判断数据是否为空
            if (entry.getValue() == null) {
                continue;
            }
            // 通过数据得到反射类
            Class<?> clazz = entry.getValue().getClass();
            String className = clazz.getName();
            // 判断是否接口类
            if (!clazz.isAnnotationPresent(RestController.class)) {
                continue;
            }

            // 判断其映射类路径
            String classPath = "";
            // 判断接口类是否包含映射注解
            if (clazz.isAnnotationPresent(RequestMapping.class)) {
                RequestMapping mapping = clazz.getAnnotation(RequestMapping.class);
                if (mapping != null && mapping.value() != null && mapping.value().length > 0) {
                    classPath = mapping.value()[0];
                }
            }

            // 获取接口类授权注解
            AnAuthorize[] classAuthorizes = null;
            if (clazz.isAnnotationPresent(AnAuthorize.class)) {
                AnAuthorize anAuthorize = clazz.getAnnotation(AnAuthorize.class);
                if (anAuthorize != null) {
                    classAuthorizes = new AnAuthorize[]{anAuthorize};
                }
            } else if (clazz.isAnnotationPresent(AnAuthorizes.class)) {
                AnAuthorizes anAuthorizes = clazz.getAnnotation(AnAuthorizes.class);
                if (anAuthorizes != null) {
                    classAuthorizes = anAuthorizes.value();
                }
            }

            // 获取接口类函数
            Method[] methods = clazz.getMethods();
            // 判断是否有函数
            if (methods == null || methods.length == 0) {
                continue;
            }

            // 遍历函数进行解析
            for (Method method : methods) {
                putMethodHandler(handlers, className, classPath, classAuthorizes, method);
            }
        }

        return handlers;
    }

    /**
     * 解析记录处理信息
     *
     * @param handlers        处理信息map
     * @param className       类名字
     * @param classPath       类路径
     * @param classAuthorizes 类菜单授权注解
     * @param method          反射方法
     * @return
     * @author LiCongLu
     * @date 2020-04-03 11:12
     */
    private static void putMethodHandler(HashMap<String, HandlerInfo> handlers, String className, String classPath, AnAuthorize[] classAuthorizes, Method method) {
        // 每次循环均初始化函数信息
        // 函数路径
        String methodPath = "";
        // 函数类型
        String methodType = "";
        StringBuilder builder = new StringBuilder();

        // 解析函数映射请求类型
        if (method.isAnnotationPresent(PostMapping.class)) {
            // 判断是否Post请求
            PostMapping mapping = method.getAnnotation(PostMapping.class);
            methodPath = mapping.value()[0];
            methodType = Constants.POST;
        } else if (method.isAnnotationPresent(GetMapping.class)) {
            // 判断是否Get请求
            GetMapping mapping = method.getAnnotation(GetMapping.class);
            methodPath = mapping.value()[0];
            methodType = Constants.GET;
        } else if (method.isAnnotationPresent(RequestMapping.class)) {
            // 判断是否映射请求
            RequestMapping mapping = method.getAnnotation(RequestMapping.class);
            methodPath = mapping.value()[0];
            // 判断
            for (RequestMethod requestMethod : mapping.method()) {
                if (builder.length() == 0) {
                    builder.append(requestMethod.name());
                } else {
                    builder.append(",").append(requestMethod.name());
                }
            }
            methodType = builder.toString();
        }

        if (methodPath.length() > 0 && methodType.length() > 0) {
            HandlerInfo handlerInfo = new HandlerInfo(className, classPath, method.getName(), methodPath, methodType);
            // 设置类授权注解
            handlerInfo.setClassAuthorizes(classAuthorizes);
            // 获取函数授权注解
            if (method.isAnnotationPresent(AnAuthorize.class)) {
                AnAuthorize anAuthorize = method.getAnnotation(AnAuthorize.class);
                if (anAuthorize != null) {
                    handlerInfo.setMethodAuthorizes(new AnAuthorize[]{anAuthorize});
                }
            } else if (method.isAnnotationPresent(AnAuthorizes.class)) {
                AnAuthorizes anAuthorizes = method.getAnnotation(AnAuthorizes.class);
                if (anAuthorizes != null) {
                    handlerInfo.setMethodAuthorizes(anAuthorizes.value());
                }
            }
            handlers.put(handlerInfo.getServletPath(), handlerInfo);
        }
    }
}
